home *** CD-ROM | disk | FTP | other *** search
/ Gamers Delight 2 / Gamers Delight 2.iso / Aminet / game / gag / PigLatin.lha / PigLatin / pig.c next >
C/C++ Source or Header  |  1986-04-08  |  16KB  |  396 lines

  1. #include "exec/types.h"               /*Filename: pig.c                  */
  2. #include "lattice/stdio.h"
  3. #include "lattice/ctype.h"            /* Copyright March, 1986 by        */
  4. #include "libraries/translator.h"     /* Thomas W. Clement.              */
  5. #include "devices/narrator.h"         /* Licence is hereby given for     */
  6. #include "exec/exec.h"                /* the non-commercial use and      */
  7. #include "exec/nodes.h"               /* duplication of all or part of   */
  8. #include "exec/memory.h"              /* this program, expressly         */
  9. #include "exec/interrupts.h"          /* conditioned, however, upon the  */
  10. #include "exec/ports.h"               /* inclusion of this copyright     */
  11. #include "exec/libraries.h"           /* notice and licencing agreement  */
  12. #include "exec/io.h"                  /* in any copy made.               */
  13. #include "exec/execbase.h"
  14.  
  15. #define REVISION 1
  16.  
  17. struct   MsgPort     *writeport      = 0;      /* Write reply port.       */
  18. struct   narrator_rb *writeNarrator  = 0;      /* Pointer to IORB.        */
  19. struct   Library     *TranslatorBase = 0;      /* Ptr to Translator fn.   */
  20.  
  21. extern   struct   MsgPort   *CreatePort();     /* External functions      */
  22. extern   struct   Library   *OpenLibrary();    /* are declared here.      */
  23.  
  24. char  obuff[1024];                     /* Buffer sent to translate device.*/
  25. char  phonemeBuff[2048];               /* Buffer for translated string.   */
  26. char  *pobuff;                         /* Pointer to obuff.               */
  27.  
  28. int   error;                           /* Error code.                     */
  29.  
  30. UWORD Rate     = 100;                  /* Rate of speaking voice. (Slower */
  31.                                        /* than usual default value.)      */
  32. UWORD Pitch    = DEFPITCH;             /* Pitch of speaking voice. (110)  */
  33. UWORD Sex      = DEFSEX;               /* Sex of speaking voice.  (Male)  */
  34. UWORD Mode     = DEFMODE;              /* Mode of voice.       (Natural)  */
  35. UWORD Sampfreq = 25000;                /* Sampling freq. (A bit higher.)  */
  36.  
  37. char  audChanMasks[4] = { 3, 5, 10, 12 };      /* Audio chan. allocation  */
  38.                                                /* map. see ch 12 ROM K.M. */
  39.  
  40. /*    This program accepts characters from stdin until a ".", "!", or "?" is
  41. *     seen, then prints the piglatin equivalent to standard output and
  42. *     uses the AMIGA's speaking abilities to say the piglatin equivalent.
  43. */
  44.  
  45. main()
  46. {
  47.       /* Main() assembles characters into words which are passed on to
  48.       *  pig() for conversion into pig latin.  An imbedded apostrophe
  49.       *  is considered a part of the word.  When a sentence is assembled,
  50.       *  it is passed on to sayit() for enunciation.
  51.       */
  52.  
  53.       char  wbuff[64];                    /* Single word buffer.        */
  54.       char  *pwbuff;                      /* Pointer to wbuff.          */
  55.       int   c;                            /* Current character.         */
  56.       int   nopig = 0;                    /* Flag for regular speech.   */
  57.       void  setup_speech();               /* Declare function.          */
  58.       void  cleanup();                    /* Declare cleanup function.  */
  59.       void  set_voice();                  /* Declare voice specifier.   */
  60.  
  61.       pobuff = obuff;                     /* Initialize pobuff.         */
  62.  
  63.       printf( "Do you want to set voice characteristics? ( y or n ): " );
  64.       gets( wbuff );
  65.       if( *wbuff == 'y' || *wbuff == 'Y' )
  66.       {
  67.          set_voice();                     /* Routine to change voice.   */
  68.       }
  69.  
  70.       printf( "Piglatin or regular speech? ( 'p' or 'r' ) :" );
  71.       gets( wbuff );
  72.       if( *wbuff == 'r' || *wbuff == 'R' )
  73.       {
  74.          nopig = -1;                      /* Set flag for normal speech.*/
  75.       }
  76.  
  77.       setup_speech();                     /* Initialize speech stuff.   */
  78.  
  79.       printf( "Enter sentences ending with \".\", \"!\" or \"?\".\n" );
  80.  
  81.       wbuff[0] = '\0';                    /* Buffer starts at wbuff[1]. */
  82.       c = getchar();                      /* Get first character.       */
  83.  
  84.       while( c != EOF )                   /* Exit cleanly on EOF.       */
  85.       {
  86.          if( Chk_Abort() )                /* Exit cleanly on ^C or ^D.  */
  87.          {
  88.             printf( "** Break **\n" );    /* Announce break on ^C or ^D.*/
  89.             break;                        /* Gets to cleanup routines.  */
  90.          }
  91.          pwbuff = wbuff + 1;              /* Pointer to 1st wbuff char. */
  92.          if( !isalpha(c) )                /* Skip all non-alphabetics.  */
  93.          {
  94.             *pobuff++ = c;                /* Add the character to obuff.*/
  95.  
  96.             if( c == '.' | c == '?' | c == '!' )   /* End of sentence?  */
  97.             {
  98.                *pobuff = '\0';            /* Null terminate obuff.      */
  99.  
  100.                if( !nopig )
  101.                {
  102.                   printf("%s\n", obuff);  /* Print what's in the buffer.*/
  103.                }
  104.                sayit();                   /* Call speech routine.       */
  105.                pobuff = obuff;            /* Reset output buffer ptr.   */
  106.             }
  107.             c = getchar();                /* Update current character.  */
  108.          }
  109.          else                             /* Collect & pass word to pig.*/
  110.          {
  111.  
  112.             while( isalpha(c) || c == '\'' )
  113.             {
  114.                *pwbuff++ = c;             /* Word - alphabetic chars &   */
  115.                c = getchar();             /* imbedded apostrophes.       */
  116.             }
  117.             *pwbuff = '\0';               /* Terminate word w/ null.     */
  118.  
  119.             if( nopig )
  120.             {
  121.                strcpy( pobuff, wbuff + 1 );          /* Copy word to     */
  122.                pobuff += pwbuff - ( wbuff + 1 );     /* obuff w/o change.*/
  123.             }
  124.             else
  125.             {
  126.                pig( wbuff + 1 );          /* Sooeey.   ( Call pig. )    */
  127.             }
  128.          }
  129.       }
  130.       cleanup();                          /* Close devices,ports, libs. */
  131.       exit( 0 );
  132. }
  133.  
  134.  
  135. pig( word )
  136. char  *word;
  137. {
  138.       /* Pig() takes a pointer to a word passed from main(), and assembles
  139.       *  the pig latin equivalent.
  140.       */
  141.  
  142.       char  *sword = word;                /* Pointer to word.            */
  143.       int   length;                       /* Length of string.           */
  144.  
  145.       if( *( sword + 1 ) == '\0' )        /* Don't change single letter  */
  146.       {                                   /* words.                      */
  147.          *pobuff++ = *sword;                     /* Add to output buff.  */
  148.          if( *sword == 'a' || *sword == 'A' )    /* Add more if word was */
  149.          {                                       /* "A" or "a"-- make it */
  150.             (void)strcpy( pobuff, "n-yay" );     /* "an-yay". (The next  */
  151.             pobuff += 5;                         /* word will start with */
  152.          }                                       /* a vowel.)            */
  153.       }
  154.       else if( isvowel( sword ) )         /* If it begins with a vowel   */
  155.       {                                   /* pigword is word with "yay"  */
  156.          length = strlen( word );         /* added to the end.           */
  157.          (void)strcpy( pobuff, word );    /* Copy word to obuff.         */
  158.          pobuff += length;                /* Advance pobuff.             */
  159.          (void)strcpy( pobuff, "-yay" );  /* Copy "-yay" to obuff.       */
  160.          pobuff += 4;                     /* Advance pobuff.             */
  161.       }
  162.       else                                /* Consonant starts a word.    */
  163.       {
  164.          while( !isvowel( sword ) && *sword != '\0' )  /* Find 1st vowel */
  165.          {                                             /* or word end.   */
  166.             ++sword;
  167.          }
  168.  
  169.          if( *sword == '\0' )              /* If there are no vowels in  */
  170.          {                                 /* the word, don't change it. */
  171.             length = strlen( word );
  172.             (void)strcpy( pobuff, word );  /* Copy the word to obuff.    */
  173.             pobuff += length;              /* Advance pobuff.            */
  174.          }
  175.          else
  176.          {
  177.             if( isupper( *word ) )         /* If upper case,             */
  178.             {
  179.                *word += 32;                /* change to lower case, and  */
  180.                *sword = toupper( *sword ); /* change new 1st lett to UC. */
  181.             }
  182.             length = strlen( sword );      /* Get length of substring.   */
  183.             (void)strcpy( pobuff, sword ); /* Copy it to obuff.          */
  184.             pobuff += length;              /* Advance pobuff.            */
  185.             *pobuff++ = '-';               /* Add a hyphen for clarity.  */
  186.             *sword = '\0';                 /* Terminate consonant part.  */
  187.             length = strlen( word );       /* Get length of cons part.   */
  188.             (void)strcpy( pobuff, word );  /* Copy cons part to obuff.   */
  189.             pobuff += length;              /* Advance pobuff.            */
  190.             (void)strcpy( pobuff, "ay" );  /* Add "ay" to the string.    */
  191.             pobuff += 2;                   /* Advance pobuff.            */
  192.          }
  193.       }
  194. }
  195.  
  196. isvowel( p )
  197. char  *p;
  198. {
  199.       /* This routine returns true if the character is a vowel.
  200.       *  For the purposes of this program, 'u' is not considered a
  201.       *  vowel if it follows a 'q'.  'Y' is considered a vowel if it
  202.       *  is followed by a consonant.  Notice that 'y' will be treated
  203.       *  as a vowel in the program only where either:
  204.       *     1. It starts a word and is followed by a consonant, or
  205.       *     2. It is preceeded by a string of only consonants and is
  206.       *        followed by a consonant.
  207.       */
  208.  
  209.       char c;           /* Current character, ( pointer to by p ).      */
  210.  
  211.       if( ( c = tolower( *p ) ) == 'a' || c == 'e' || c == 'i' || c == 'o'
  212.             || ( c == 'u' && tolower( *( p-1 ) ) != 'q' )
  213.             || ( c == 'y' && !isvowel( p + 1 ) ) )
  214.       {
  215.          return 1;      /* Return true if a "vowel" as we define it.    */
  216.       }
  217.       return 0;         /* Otherwise return false. */
  218. }
  219.  
  220.  
  221. void  setup_speech()
  222. {
  223.    /* This function sets up the translator library and the speech device of
  224.    *  the AMIGA.  If it fails for some reason, it trys to let you know why.
  225.    */
  226.  
  227.    if((TranslatorBase = OpenLibrary("translator.library", REVISION)) == NULL)
  228.    {
  229.       printf( "Can't open Translator library.\n" );
  230.       error = 1;
  231.       cleanup();
  232.    }
  233.  
  234.    if( ( writeport = CreatePort( 0, 0 ) ) == NULL )
  235.    {
  236.       printf( "CreatePort problems.\n" );
  237.       error = 2;
  238.       cleanup();
  239.    }
  240.  
  241.    /* Note that memory is allocated directly, instead of using the
  242.    *  function CreateExtIO().  This is because I couldn't find this
  243.    *  function anywhere in my release.  Anyway, this seems to work O.K.
  244.    *  so I suppose I can't complain.
  245.    */
  246.    if( ( writeNarrator = (struct narrator_rb *)AllocMem( sizeof(
  247.         struct narrator_rb), MEMF_PUBLIC | MEMF_CLEAR  ) ) == NULL )
  248.    {
  249.       printf( "Can't allocate memory for writeNarrator IORB.\n" );
  250.       error = 3;
  251.       cleanup();
  252.    }
  253.  
  254.    /* Specify the type of node in the linked list,  the priority of the
  255.    *  message, and the address of the prot created with CreatePort().
  256.    */
  257.    writeNarrator->message.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  258.    writeNarrator->message.io_Message.mn_Node.ln_Pri  = 0;
  259.    writeNarrator->message.io_Message.mn_ReplyPort    = writeport;
  260.  
  261.    writeNarrator->ch_masks = audChanMasks;           /* Audio channels.   */
  262.    writeNarrator->nm_masks = sizeof( audChanMasks ); /* # of Audio chans. */
  263.    writeNarrator->message.io_Command = CMD_WRITE;    /* Command for IO.   */
  264.  
  265.    if( OpenDevice( "narrator.device", 0, writeNarrator, 0 ) )
  266.    {
  267.       printf( "Can't open narrator device.\n" );
  268.       error = 4;
  269.       cleanup();
  270.    }
  271.    writeNarrator->rate     = Rate;             /* Set these values to the */
  272.    writeNarrator->pitch    = Pitch;            /* defaults, or the user   */
  273.    writeNarrator->sex      = Sex;              /* specified values if the */
  274.    writeNarrator->mode     = Mode;             /* function set_voice was  */
  275.    writeNarrator->sampfreq = Sampfreq;         /* called.                 */ 
  276.  
  277.    return;
  278. }
  279.  
  280. void  cleanup()
  281. {
  282.    if( writeNarrator )                /* If the narrator device had been  */
  283.    {                                  /* close it & free up memory.       */
  284.       CloseDevice( writeNarrator );
  285.       FreeMem( writeNarrator, sizeof( struct narrator_rb ) );
  286.    }
  287.  
  288.    if( writeport )
  289.    {                                           /* If the port had been    */
  290.       DeletePort( writeport );                 /* created, delete it.     */
  291.    }
  292.  
  293.    if( TranslatorBase )                        /* If the translator       */
  294.    {                                           /* library had been opened,*/
  295.       CloseLibrary( TranslatorBase );          /* close it.               */
  296.    }
  297.  
  298.    if( error )                        /* Tell user what went wrong.       */
  299.    {
  300.       fprintf( stderr, "Error #%d, execution terminated.\n", error );
  301.       exit( error );
  302.    }
  303. }
  304.  
  305.  
  306. sayit()
  307. {
  308.    /* This function speaks the pig latin.  It translates the string in
  309.    *  obuff, placing the result in phonemeBuff.  It then sets a couple
  310.    *  of fields in the narrator IORB  (Input Output Request Block), and
  311.    *  sends the phonemes into the ether.
  312.    */
  313.  
  314.    if( Translate( obuff, pobuff-obuff, phonemeBuff, 2048 ) )
  315.    {
  316.       printf( "Translator output buffer overflow.\n" );
  317.       error = 5;
  318.       cleanup();
  319.    }
  320.  
  321.    writeNarrator->message.io_Data   = (APTR)phonemeBuff;   /* Ph. source. */
  322.    writeNarrator->message.io_Length = strlen(phonemeBuff); /* Length.     */
  323.  
  324.    if( DoIO( writeNarrator ) )
  325.    {
  326.       printf( "Can't perform DoIO.\n" );
  327.       error = 6;
  328.       cleanup();
  329.    }
  330. }
  331.  
  332. int   atoi(s)
  333. char  *s;       /* This is a simple version of atoi suitable for our use. */
  334. {               /* ( atoi changes a string into an integer ).             */
  335.    int   n;
  336.  
  337.    for( n = 0; *s >= '0' && *s <= '9'; s++ )
  338.    {
  339.       n = 10 * n + *s - '0';
  340.    }
  341.    return( n );
  342. }
  343.  
  344.  
  345.  
  346.  
  347. void set_voice()
  348. {
  349.    char  answer[10];                            /* Char array for answers.*/
  350.  
  351.    printf( "Male or female? ( m or f ): " );
  352.    gets( answer );
  353.    if( *answer == 'f' || *answer == 'F' )
  354.    {
  355.       Sex = FEMALE;
  356.    }
  357.  
  358.    printf( "How many words per minute? (40 to 400): " );
  359.    gets( answer );
  360.    if( *answer != '\0' )
  361.    {
  362.       Rate = atoi( answer );                    /* Convert answer to int. */
  363.       Rate = max( Rate, MINRATE );              /* Make Rate >= minimum.  */
  364.       Rate = min( Rate, MAXRATE );              /* Make Rate <= maximum.  */
  365.    }
  366.  
  367.    printf( "What pitch speech? (65 to 320): " );
  368.    gets( answer );
  369.    if( *answer != '\0' )
  370.    {
  371.       Pitch = atoi( answer );                   /* Convt answer to int.   */
  372.       Pitch = max( Pitch, MINPITCH );           /* Make Pitch >= minimum. */
  373.       Pitch = min( Pitch, MAXPITCH );           /* Make Pitch <= maximum. */
  374.    }
  375.  
  376.    printf( "What sampling frequency? ( 5000 to 28000 ): " );
  377.    gets( answer );
  378.    if( *answer != '\0' )
  379.    {
  380.       Sampfreq = atoi( answer );                /* Convt answer to int.  */
  381.       Sampfreq = max( Sampfreq, MINFREQ );      /* Ensure that sampling  */
  382.       Sampfreq = min( Sampfreq, MAXFREQ );      /* freq is w/in range.   */
  383.    }
  384.  
  385.    printf( "What mode of speech? (Natural or Monotone): " );
  386.    gets( answer );
  387.    if ( *answer == 'M' || *answer == 'm' )
  388.    {
  389.       Mode = ROBOTICF0;                         /* Monotone voice.        */
  390.    }
  391.    return;
  392. }
  393.  
  394.  
  395.  
  396.